package com.yiji.fintech.musfinance.common.service;

import com.acooly.core.common.service.EntityService;
import com.acooly.core.utils.Collections3;
import com.acooly.core.utils.GenericsUtils;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import com.yiji.fintech.musfinance.center.notify.order.base.NotifyOrderBase;
import com.yiji.fintech.musfinance.common.annotation.NotifyAnnotation;
import com.yiji.fintech.musfinance.common.annotation.Order2Domain2Event;
import com.yiji.fintech.musfinance.common.context.SpringApplicationContext;
import com.yiji.fintech.musfinance.common.domain.base.BaseDomain;
import com.yiji.fintech.musfinance.common.exception.ReflectDbServiceException;
import com.yiji.fintech.musfinance.common.exception.ReflectEntityException;
import com.yiji.fintech.musfinance.common.strategy.notify.AbstractNotifyStrategy;
import com.yiji.fintech.musfinance.common.utils.object.GatewayObjectAccessor;
import com.yiji.fintech.musfinance.common.enginerules.SuperRouteService;
import com.yiji.fintech.musfinance.entity.AbstractTransaction;

import java.util.List;
import java.util.Map;

/**
 * 操作服务工具类
 * Created by ouwen@yiji.com} on 2017/9/18.
 */
public class OpratorService {
    /**
     * 路由服务
     */
    private SuperRouteService superRouteService;
    /**
     * db操作服务
     */
    public EntityService<AbstractTransaction> service;
    /**
     * db操作实体
     */
    public AbstractTransaction entity;
    /**
     * 初始化DB服务
     * @param domain
     */
    public void initDbService(BaseDomain domain){
        service = getDbService(domain);
    }

    /**
     * 初始化DB服务
     * @param strategy
     */
    public void initDbService(AbstractNotifyStrategy strategy){
        service = getDbService(strategy);
    }

    /**
     * 容器获取路由服务
     * @return
     */
    protected SuperRouteService getSuperRouteService(){
       return (SuperRouteService)SpringApplicationContext.getBeanByClass(SuperRouteService.class);
    }

    /**
     * 获取Domain注解中数据库操作服务
     * @param domain
     * @return
     */
    protected EntityService getDbService(BaseDomain domain){
        Order2Domain2Event order2Domain2Event = domain.getClass().getAnnotation(Order2Domain2Event.class);
        Class dbService = order2Domain2Event.dbServiceClass();
        return getDbService(dbService);
    }

    /**
     * 获取NotifyStrategy注解中数据库服务
     * @param notifyStrategy
     * @return
     */
    protected EntityService getDbService(AbstractNotifyStrategy notifyStrategy){
        NotifyAnnotation notifyAnnotation = notifyStrategy.getClass().getAnnotation(NotifyAnnotation.class);
        Class dbService = notifyAnnotation.dbServiceClass();
        return getDbService(dbService);
    }

    /**
     * 通过dbService Class找到服务
     * @param dbService
     * @return
     */
    protected EntityService getDbService(Class dbService){
        if(dbService != null){
            return  (EntityService) SpringApplicationContext.getBeanByClass(dbService);
        }
        throw new ReflectDbServiceException("Domain【"+dbService.getClass().getName()+"】未正确配置DBService服务");
    }
    public void initEntity(BaseDomain domain){
        if(service == null){
            initDbService(domain);
        }
        entity = getEntity(domain,service);
    }

    /**
     * 通过流水号找到实体
     * @param notifyOrder
     */
    public void findEntity(NotifyOrderBase notifyOrder){
        Map<String,Object> params = Maps.newHashMap();
        params.put("EQ_bizOrderNo",notifyOrder.getBizOrderNo());
        List datas = service.query(params,null);
        if(Collections3.isNotEmpty(datas)){
            entity = (AbstractTransaction)datas.get(0);
        }
    }
    /**
     * 通过流水号找到实体
     * @param domain
     */
    public void findEntity(BaseDomain domain){
        if(service == null){
            initDbService(domain);
        }
        Map<String,Object> params = Maps.newHashMap();
        params.put("EQ_bizOrderNo",domain.getBizOrderNo());
        params.put("EQ_merchOrderNo",domain.getMerchOrderNo());
        List datas = service.query(params,null);
        if(Collections3.isNotEmpty(datas)){
            entity = (AbstractTransaction)datas.get(0);
        }
    }
    /**
     * 设置请求对象值
     *
     * @param objectAccessor
     * @param key
     */
    protected void setFieldValue(GatewayObjectAccessor<AbstractTransaction> objectAccessor, Map<String, String> source, String key) {
        Object value = source.get(key);
        if (!Strings.isNullOrEmpty((String) value)) {
            objectAccessor.setPropertyValue(key, value);
        }
    }
    /**
     * 获取服务对应实体
     * @param domain
     * @param service
     * @return
     */
    protected AbstractTransaction getEntity(BaseDomain domain, EntityService service){
        try {
            Class  entityClass = GenericsUtils.getSuperClassGenricType(service.getClass().getSuperclass());
            AbstractTransaction entity = (AbstractTransaction)entityClass.newInstance();
            GatewayObjectAccessor<BaseDomain> domainObjectAccessor = GatewayObjectAccessor.of(domain);
            Map<String, String> source = domainObjectAccessor.getAllDataExcludeTransient();
            GatewayObjectAccessor<AbstractTransaction> objectAccessor = GatewayObjectAccessor.of(entity);
            for (Map.Entry<String, String> entry : source.entrySet()) {
                setFieldValue(objectAccessor, source, entry.getKey());
            }
            return entity;
        } catch (InstantiationException | IllegalAccessException e) {
            throw new ReflectEntityException("反射Domain【"+domain.getClass().getName()+"】到实体异常");
        }
    }
}
